ページキャッシュ
============

ページキャッシュはページの内容全てをキャッシュすることを指します。
ページキャッシュは、異なった場所で発生する可能性があります。
たとえば、適切なページヘッダーを使えば、クライアントブラウザがページを有効期限付きでキャッシュするでしょう。
また、ウェブアプリケーション自身も、ページのコンテンツをキャッシュとして保存できます。

アウトプットキャッシュ
---------------------
ページキャッシュは [フラグメントキャッシュ](/doc/guide/caching.fragment) の特殊な形態と捉えられます。
ページの内容の多くはビューにレイアウトを適用して生成されるため、レイアウトの中で単純に [beginCache()|CBaseController::beginCache] と [endCache()|CBaseController::endCache] を呼び出してもキャッシュは動作しません。
なぜなら、レイアウトは、コンテンツビューが評価された後に、[CController::render()] メソッド中で適用されるからです。

ページ全体をキャッシュするには、ページ内容を生成するアクションの実行を跨ぐようにしなければいけません。
これを行うためには、[COutputCache] を [フィルタ](/doc/guide/basics.controller#sec-5) アクションとして使用します。
キャッシュフィルタの設定方法を下記に示します:

~~~
[php]
public function filters()
{
	return array(
		array(
			'COutputCache',
			'duration'=>100,
			'varyByParam'=>array('id'),
		),
	);
}
~~~

上記のフィルタの設定は、コントローラのすべてのアクションに適用されるフィルタを指定しています。
プラスの演算子だけを使い、一つまたはいくつかのアクションのみにフィルタを制限することもできます。
詳細については、[フィルタ](/doc/guide/basics.controller#sec-5) を参照してください。

> Tip|ヒント: [COutputCache] は、 [CFilterWidget] より継承されているために、フィルタとして使用することが出来ます。
実際、ウィジェットの動作はフィルタにとても似ています。
ウィジェット (フィルタ) は、それに含まれているコンテンツ (アクション) が評価される前に動作が始まり、そして、含まれているコンテンツ (アクション) が評価された後に、ウィジェット (フィルタ) が終了します。

HTTP キャッシュ
------------
Yii は、アクションの出力の単純なキャッシュに加えて、バージョン 1.1.11 において [CHttpCacheFilter] を導入しました。
このフィルターは、前述のヘッダ (ページの内容が最後のリクエストの時から変更されていないことをクライアントに通知するためのヘッダ) を設定する手助けをしてくれます。
これによってサーバはコンテンツを再送しなくてよくなります。
[CHttpCacheFilter] は [COutputCache] と同じ様にして設定することが出来ます。
~~~
[php]
public function filters()
{
	return array(
		array(
			'CHttpCacheFilter + index',
			'lastModified'=>Yii::app()->db->createCommand("SELECT MAX(`update_time`) FROM {{post}}")->queryScalar(),
		),
	);
}
~~~
上記のコードは、`Last-Modified` ヘッダを記事が更新された日時に設定します。
また、[CHttpCacheFilter::lastModifiedExpression] を利用して、php の式を使って `Last-Modified` ヘッダを設定することも出来ます。

> Tip|ヒント: [CHttpCacheFilter::lastModifiedExpression] と [CHttpCacheFilter::lastModified] は、両方とも、Unix タイムスタンプを表わす整数か、任意の形式の日付文字列を受け入れることが出来ます。
後者については、[strtotime()](http://php.net/manual/function.strtotime.php) によって解釈できる形式である限り、更なる変換は必要ありません。

"Entity Tag" (または略して `ETag`) ヘッダも同様に、[CHttpCacheFilter::etagSeed] および [CHttpCacheFilter::etagSeedExpression] によって設定することが出来ます。
両方ともシリアライズされた値 (従って単一の値を使うことも、配列を使うことも出来ます) から印字可能な base64 エンコードされた SHA1 ハッシュを生成して、`ETag` ヘッダの内容として使用します。
これは [Apache ウェブサーバ](http://httpd.apache.org) や他のサーバが ETag を生成する方法とは異なります。
しかし、この手法は完璧に RFC にのっとっていますし、フレームワークでの使用にはより適したものであることが分っています。

> 注意: [RFC 2616, section 13.3.4](http://tools.ietf.org/html/rfc2616#section-13.3.4) を遵守するために、[CHttpCacheFilter] は、両方とも生成出来る場合には、`ETag` **および** `Last-Modified` の両方のヘッダを送出します。
結果として、クライアントに送られたとき、両方がキャッシュ評価に使用されます。

"Entity Tag" はハッシュであるため、`Last-Modified` ヘッダよりも、複雑あるいは精密なキャッシュ制御を可能にします。
例えば、サイトが別のテーマに移ったときなどにも、ETag によってキャッシュを無効化することが出来ます。

> Tip|ヒント: [CHttpCacheFilter::etagSeedExpression] に負荷の高い式を指定すると、[CHttpCacheFilter] の本来の目的を損なって、不必要なオーバーヘッドを導入することになる場合があります。
なぜなら、[CHttpCacheFilter::etagSeedExpression] は、リクエストごとに再評価されるからです。
ページの **内容** が変更されたときにキャッシュを無効化するための単純な式を指定するようにして下さい。

### SEO に対する影響
検索エンジンのボットはキャッシュヘッダを尊重する傾向があります。
クローラの中には、一定期間内に処理するドメインごとのページ数に制限を持っているものもあるため、キャッシュヘッダを導入して、処理の必要があるページ数を減らしてやると、サイトのインデックスの作成を促進できるかも知れません。

<div class="revision">$Id$</div>
